<template>
  <div class="notice-page-box">
    <!-- 搜索表单 -->
    <search-form-qvil
      v-model="queryForm"
      :affixed="true"
      :fields="searchFields"
      :inline="true"
      :loading="tableState.loading"
      :show-label="false"
      @form-change="handleFormChange"
      @reset="handleReset"
      @search="handleSearch"
    >
      <template #actions>
        <el-button type="primary" @click="handleAdd">新增{{ moduleName }}</el-button>
      </template>
    </search-form-qvil>

    <!-- 表格 -->
    <table-qvil
      v-model:page="queryForm.page"
      v-model:page-size="queryForm.limit"
      :border="true"
      class="notice-table"
      :columns="tableState.visibleColumns"
      :data="tableState.data"
      :loading="tableState.loading"
      row-key="id"
      :show-index="true"
      :stripe="true"
      :total="tableState.pagination.total"
      @page-change="handlePageChange"
      @size-change="handleSizeChange"
    >
      <!-- 通知类型 -->
      <template #column-notifyType="{ row }">
        <div>{{ statusDict.notifyType[row.notifyType] || row.notifyType }}</div>
      </template>

      <!-- 通知内容 -->
      <template #column-content="{ row }">
        <div class="content-preview" v-html="row.content || '未获取到内容'"></div>
      </template>

      <!-- 附件列 -->
      <template #column-attachment="{ row }">
        <div v-if="row.attachment && row.attachment.length > 0" class="attachment-section">
          <div class="attachment-list">
            <div v-for="(item, index) in row.attachment" :key="index" class="attachment-item">
              <div class="file-info">
                <div class="file-icon">
                  <i :class="getFileIcon(item.name)"></i>
                </div>
                <div class="file-details">
                  <div class="file-name">{{ item.name }}</div>
                  <div class="file-meta">{{ formatFileSize(item.size || 0) }}</div>
                </div>
              </div>
              <div class="attachment-actions">
                <el-button size="small" text type="primary" @click="handleDownload(item)">
                  <el-icon><download /></el-icon>
                </el-button>
              </div>
            </div>
          </div>
        </div>
      </template>

      <!-- 操作列 -->
      <template #column-operations="{ row }">
        <div class="operations-container">
          <el-button size="small" text type="info" @click="handleDetails(row)">
            <el-icon class="button-icon"><info-filled /></el-icon>
            详情
          </el-button>
          <el-button size="small" text type="danger" @click="handleDelete(row)">
            <el-icon class="button-icon"><delete /></el-icon>
            删除
          </el-button>
        </div>
      </template>
    </table-qvil>

    <!-- 表单弹窗 -->
    <form-dialog-qvil
      ref="formDialogRef"
      v-model="dialogState.visible"
      :confirm-loading="dialogState.confirmLoading"
      :error="dialogState.error"
      :fields="getFormFields"
      :form-data="dialogState.formData"
      :loading="dialogState.loading"
      :title="dialogState.title"
      @cancel="handleFormCancel"
      @confirm="handleConfirmForm"
      @validation-error="handleValidationError"
    >
      <!-- 使用插槽添加富文本编辑器和会议议程功能 -->
      <template #form-content>
        <!-- 自定义接收人选择器 -->
        <el-form-item label="接收人" prop="userId">
          <recipient-selector
            v-model="dialogState.formData.userId"
            :activity-id="getActivityId()"
            @update:model-value="handleRecipientChange"
          />
        </el-form-item>

        <el-form-item label="通知内容" prop="content">
          <quill-editor v-model="dialogState.formData.content" class="content-editor" placeholder="请输入通知内容..." />
        </el-form-item>
      </template>
    </form-dialog-qvil>

    <!-- 通知详情弹窗 -->
    <notice-detail v-if="currentDetailTaskId !== null" v-model="detailDialogVisible" :task-id="currentDetailTaskId" />
  </div>
</template>

<script lang="ts" setup>
import { Delete, Download, InfoFilled } from '@element-plus/icons-vue'
import dayjs from 'dayjs'
import { ElMessage, ElMessageBox } from 'element-plus'
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
import NoticeDetail from './components/NoticeDetail.vue'
import RecipientSelector from './components/RecipientSelector.vue'
import type { NotificationTask } from './config'
import { formFields, getUserList, moduleApi, moduleName, parseApiData, searchFields, statusDict, tableColumns } from './config'
import QuillEditor from '/@/components/quill/QuillEditor.vue'
import type { ApiResponse } from '/@/types/api'
import { getActivityId, getCurrentMeetingTitle } from '/@/utils/activityHelper'
import request from '/@/utils/request'

// 类型定义
interface QueryForm {
  notifyType: string
  notifySendStatus: string
  title: string
  activityId: string
  page: number
  limit: number
}

const actualRecipients = ref<string | string[]>([])
const recipientDeptId = ref<string>('')

const queryForm = ref<QueryForm>({
  notifyType: '',
  notifySendStatus: '',
  title: '',
  activityId: getActivityId(),
  page: 1,
  limit: 20,
})

const tableState = reactive({
  data: [] as NotificationTask[],
  loading: false,
  pagination: {
    total: 0,
    page: 1,
    pageSize: 20,
  },
  visibleColumns: tableColumns,
})

const dialogState = reactive({
  visible: false,
  title: `新增${moduleName}`,
  formData: {} as NotificationTask,
  loading: false,
  confirmLoading: false,
  error: '',
})

// 详情弹窗相关状态
const detailDialogVisible = ref(false)
const currentDetailTaskId = ref<string | null>(null)

const isEditMode = ref(false)
const formDialogRef = ref()

const getFileIcon = (fileName: string) => {
  const extension = fileName.split('.').pop()?.toLowerCase()
  const iconMap: Record<string, string> = {
    pdf: 'el-icon-document',
    doc: 'el-icon-document',
    docx: 'el-icon-document',
    xls: 'el-icon-document',
    xlsx: 'el-icon-document',
    ppt: 'el-icon-document',
    pptx: 'el-icon-document',
    txt: 'el-icon-document',
    zip: 'el-icon-folder',
    rar: 'el-icon-folder',
    jpg: 'el-icon-picture',
    jpeg: 'el-icon-picture',
    png: 'el-icon-picture',
    gif: 'el-icon-picture',
  }
  return iconMap[extension || ''] || 'el-icon-document'
}

const formatFileSize = (size: number) => {
  if (size < 1024) {
    return `${size} B`
  } else if (size < 1024 * 1024) {
    return `${(size / 1024).toFixed(2)} KB`
  } else if (size < 1024 * 1024 * 1024) {
    return `${(size / (1024 * 1024)).toFixed(2)} MB`
  } else {
    return `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB`
  }
}

const getList = async () => {
  try {
    tableState.loading = true
    const params: Record<string, any> = {
      notifyType: queryForm.value.notifyType,
      notifySendStatus: queryForm.value.notifySendStatus,
      title: queryForm.value.title,
      page: queryForm.value.page,
      limit: queryForm.value.limit,
      activityId: queryForm.value.activityId,
    }
    const res = (await request({
      url: moduleApi,
      method: 'get',
      params,
    })) as unknown as ApiResponse<any>
    if (res && res.code === 0 && res.result) {
      tableState.data = res.result.rows.map((item: any) => parseApiData(item))
      tableState.pagination.total = res.result.count || 0
    } else {
      tableState.data = []
      tableState.pagination.total = 0
    }
  } catch (error) {
    console.error('获取数据异常:', error)
    ElMessage.error('获取数据异常')
    tableState.data = []
    tableState.pagination.total = 0
  } finally {
    tableState.loading = false
  }
}

const handleSearch = () => {
  queryForm.value.page = 1
  getList()
}

const handleFormChange = () => {}

const handleReset = () => {
  queryForm.value = {
    notifyType: '',
    notifySendStatus: '',
    title: '',
    activityId: getActivityId(),
    page: 1,
    limit: 20,
  }
  getList()
}

const handlePageChange = (page: number) => {
  queryForm.value.page = page
  getList()
}

const handleSizeChange = (size: number) => {
  queryForm.value.limit = size
  queryForm.value.page = 1
  getList()
}

const handleAdd = () => {
  dialogState.title = `新增${moduleName}`
  dialogState.formData = {
    title: '',
    notifyType: 'app',
    notifySendStatus: '0',
    content: '',
    userId: [],
    notifyTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
    activityId: getActivityId(),
  } as NotificationTask
  actualRecipients.value = []
  dialogState.visible = true
  isEditMode.value = false
  handleDialogOpen()
  nextTick(() => {
    refreshAgendaContent()
  })
}

// 处理详情：打开弹窗显示 NoticeDetail
const handleDetails = (row: NotificationTask) => {
  if (row.id === undefined) {
    ElMessage.warning('任务ID无效，无法查看详情')
    return
  }
  currentDetailTaskId.value = String(row.id)
  detailDialogVisible.value = true
}

const handleDelete = (row: NotificationTask) => {
  ElMessageBox.confirm(`确定要删除 "${row.title}" 的通知吗？`, '删除确认', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      try {
        const res = (await request({
          url: `${moduleApi}/${row.id}`,
          method: 'delete',
        })) as unknown as ApiResponse<any>
        if (res && res.code === 0) {
          ElMessage.success('删除成功')
          getList()
        } else {
          ElMessage.error(res?.message || '删除失败')
        }
      } catch (error) {
        console.error('删除数据异常:', error)
        ElMessage.error('删除数据异常')
      }
    })
    .catch(() => {
      console.log('取消删除')
    })
}

const handleDownload = async (file: any) => {
  try {
    const response = await request({
      url: file.url,
      method: 'get',
      responseType: 'blob',
    })
    if (!response.data) {
      throw new Error('下载数据为空')
    }
    const blob = new Blob([response.data])
    const link = document.createElement('a')
    link.href = window.URL.createObjectURL(blob)
    link.download = file.name
    link.click()
    window.URL.revokeObjectURL(link.href)
  } catch (error) {
    console.error('下载失败:', error)
    ElMessage.error('下载失败')
  }
}

const handleFormCancel = () => {
  dialogState.visible = false
  dialogState.formData = {} as NotificationTask
  actualRecipients.value = []
}

const getFormFields = computed(() => {
  return formFields.value.filter((field) => field.prop !== 'content')
})

const handleRecipientChange = (value: string | string[]) => {
  if (value === null || value === undefined) {
    value = []
  }
  if (value === 'all') {
    dialogState.formData.isAllUsers = true
    dialogState.formData.userId = 'all'
    dialogState.formData._userIdBackup = 'all'
    actualRecipients.value = 'all'
  } else if (Array.isArray(value)) {
    dialogState.formData.isAllUsers = false
    dialogState.formData.userId = [...value]
    dialogState.formData._userIdBackup = [...value]
    actualRecipients.value = [...value]
  } else if (typeof value === 'string' && value !== '') {
    dialogState.formData.isAllUsers = false
    dialogState.formData.userId = [value]
    dialogState.formData._userIdBackup = [value]
    actualRecipients.value = [value]
  } else {
    dialogState.formData.isAllUsers = false
    dialogState.formData.userId = []
    dialogState.formData._userIdBackup = []
    actualRecipients.value = []
  }
  dialogState.formData.deptId = undefined
  recipientDeptId.value = ''
}

const handleConfirmForm = async (formDataFromDialog: NotificationTask) => {
  try {
    if (!formDataFromDialog) {
      ElMessage.error('表单数据为空，无法提交')
      return
    }
    const currentContent = dialogState.formData.content
    dialogState.formData = formDataFromDialog
    dialogState.formData.content = currentContent
    if (!dialogState.formData.activityId) {
      dialogState.formData.activityId = getActivityId()
    }
    if (!dialogState.formData.notifyType) {
      dialogState.formData.notifyType = 'app'
    }
    if (actualRecipients.value && actualRecipients.value !== '') {
      if (actualRecipients.value === 'all') {
        dialogState.formData.isAllUsers = true
        dialogState.formData.userId = 'all'
      } else if (Array.isArray(actualRecipients.value)) {
        dialogState.formData.isAllUsers = false
        dialogState.formData.userId = [...actualRecipients.value]
      } else {
        dialogState.formData.isAllUsers = false
        dialogState.formData.userId = []
      }
    }
    await handleSubmitForm()
  } catch (error) {
    console.error('数据处理异常:', error)
    ElMessage.error('数据处理异常')
    dialogState.confirmLoading = false
  }
}

const handleSubmitForm = async () => {
  try {
    dialogState.confirmLoading = true
    dialogState.error = ''
    if (!dialogState.formData.title) {
      ElMessage.error('请输入任务名称')
      dialogState.error = '请输入任务名称'
      dialogState.confirmLoading = false
      return
    }
    if (
      dialogState.formData.userId === null ||
      dialogState.formData.userId === undefined ||
      dialogState.formData.userId === '' ||
      (Array.isArray(dialogState.formData.userId) && dialogState.formData.userId.length === 0)
    ) {
      ElMessage.error('请选择接收人')
      dialogState.confirmLoading = false
      return
    }
    const data = JSON.parse(JSON.stringify(dialogState.formData))
    if (data.userId === 'all') {
      // keep 'all'
    } else if (Array.isArray(data.userId)) {
      if (data.userId.length === 0) {
        ElMessage.error('请选择接收人')
        dialogState.confirmLoading = false
        return
      }
      data.userId = data.userId.join(',')
    } else if (typeof data.userId === 'string' && data.userId !== 'all' && data.userId !== '') {
      // keep string id
    } else {
      ElMessage.error('接收人数据格式错误')
      dialogState.confirmLoading = false
      return
    }
    let res
    if (isEditMode.value) {
      res = await request({
        url: `${moduleApi}/${data.id}`,
        method: 'put',
        data,
      })
    } else {
      res = await request({
        url: moduleApi,
        method: 'post',
        data,
      })
    }
    if (res && res.code === 0) {
      ElMessage.success(isEditMode.value ? '编辑成功' : '新增成功')
      dialogState.visible = false
      getList()
    } else {
      dialogState.error = res?.message || '操作失败'
      ElMessage.error(dialogState.error)
    }
  } catch (error: any) {
    console.error('表单提交异常:', error)
    const errorMsg = error.response?.data?.message || error.message || '操作失败'
    dialogState.error = errorMsg
    ElMessage.error(errorMsg)
  } finally {
    dialogState.confirmLoading = false
  }
}

const handleValidationError = (errorFields: any) => {
  console.error('表单验证错误:', errorFields)
  const firstError = errorFields[0]
  if (firstError && firstError.message) {
    dialogState.error = firstError.message as string
  } else {
    dialogState.error = '表单验证失败，请检查输入'
  }
}

onMounted(() => {
  getList()
})

const refreshAgendaContent = async () => {
  if (!dialogState.formData) {
    return
  }
  try {
    dialogState.loading = true
    // 动态获取会议标题，设置预设通知内容
    const meetingTitle = getCurrentMeetingTitle()
    if (meetingTitle) {
      dialogState.formData.content = `您有一条关于"${meetingTitle}"的通知，请到工作台-现场会议查看。`
    } else {
      dialogState.formData.content = '您有一条会议通知，请到工作台-现场会议查看。'
    }
    nextTick(() => {
      console.log('表单内容已加载 (refreshAgendaContent)')
    })
  } catch (error) {
    console.error('refreshAgendaContent 内部发生错误:', error)
    ElMessage.error('内容刷新时发生错误')
  } finally {
    dialogState.loading = false
  }
}

const handleDialogOpen = () => {
  getUserList()
}
</script>

<style lang="scss" scoped>
.notice-page-box {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 66px);
  overflow: hidden;
}

.receiver-container {
  display: flex;
  flex-direction: column;
  gap: 8px;
  .select-all-checkbox {
    display: flex;
    gap: 8px;
    align-items: center;
  }
  .receiver-select {
    width: 100%;
  }
}

.notice-table {
  flex: 1;
  min-height: 0;
}

.content-header {
  display: flex;
  justify-content: space-between;
  margin-bottom: 12px;
}

.switch-container {
  display: flex;
  gap: 16px;
  align-items: center;
}

:deep(.content-editor) {
  .ql-container {
    min-height: 120px;
    padding: 8px 12px;
    overflow-y: auto;
    font-size: 15px;
    line-height: 1.6;
    background: #fff;
    border: 1px solid #e5e6eb;
    border-bottom-right-radius: 8px;
    border-bottom-left-radius: 8px;
  }
  .ql-editor {
    padding: 15px;
  }
  .ql-toolbar {
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
  }
}

.content-preview {
  max-height: 100px;
  padding: 8px;
  overflow-y: auto;
  background-color: #f5f7fa;
  border-radius: 4px;
}

.attachment-section {
  .attachment-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
  }
  .attachment-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px;
    background-color: #f5f7fa;
    border-radius: 4px;
    .file-info {
      display: flex;
      gap: 12px;
      align-items: center;
      .file-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 32px;
        height: 32px;
        font-size: 16px;
        color: #606266;
        background-color: #e9eef3;
        border-radius: 4px;
      }
      .file-details {
        display: flex;
        flex-direction: column;
        gap: 4px;
        .file-name {
          font-size: 13px;
          font-weight: 500;
          color: #303133;
        }
        .file-meta {
          font-size: 11px;
          color: #909399;
        }
      }
    }
    .attachment-actions {
      display: flex;
      gap: 8px;
    }
  }
}

.operations-container {
  display: flex;
  gap: 8px;
  align-items: center;
  .button-icon {
    margin-right: 4px;
  }
}

.dialog-actions {
  margin-top: 24px;
  text-align: center;
  > * + * {
    margin-left: 16px;
  }
}
</style>
